﻿using System;
using System.Windows.Input;

namespace Foundation
{
    /// <summary>
    /// Simple command implementation.
    /// </summary>
    public class SimpleCommand : ICommand
    {
        private bool _lastCanExecuteState;

        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleCommand"/> class.
        /// </summary>
        /// <param name="onExecute">The on execute.</param>
        /// <param name="onCanExecute">The on can execute.</param>
        public SimpleCommand(Proc onExecute, Func<object,bool> onCanExecute = null)
        {
            if (onExecute != null)
                OnExecute += onExecute;

            if (onCanExecute != null)
                OnCanExecute += onCanExecute;
        }

        public delegate void Proc(object parameter);

        /// <summary>
        /// Occurs when changes occur that affect whether or not the command should execute.
        /// </summary>
        public event EventHandler CanExecuteChanged;

        public Proc OnExecute = o => { };

        public Func<object, bool> OnCanExecute = o => true;

        /// <summary>
        /// Defines the method to be called when the command is invoked.
        /// </summary>
        /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
        public void Execute(object parameter)
        {
            OnExecute(parameter);
            CanExecute(parameter);
        }

        /// <summary>
        /// Defines the method that determines whether the command can execute in its current state.
        /// </summary>
        /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
        /// <returns>
        /// true if this command can be executed; otherwise, false.
        /// </returns>
        public bool CanExecute(object parameter)
        {
            var canExecute = OnCanExecute(parameter);
            var canExecuteChanged = canExecute != _lastCanExecuteState;
            _lastCanExecuteState = canExecute;
            if (canExecuteChanged) CanExecuteChanged(this, EventArgs.Empty);
            return canExecute;
        }
    }
}
